import React, { useState, useEffect, useRef, useCallback } from 'react';
import {
  Card,
  Typography,
  Button,
  Space,
  Input,
  Select,
  Slider,
  Switch,
  Row,
  Col,
  Statistic,
  Spin,
  message,
  Drawer,
  List,
  Divider,
  Tooltip,
} from 'antd';
import {
  ReloadOutlined,
  ZoomInOutlined,
  ZoomOutOutlined,
  FullscreenOutlined,
  SearchOutlined,
  EyeOutlined,
  EyeInvisibleOutlined,
  SettingOutlined,
  InfoCircleOutlined,
} from '@ant-design/icons';
import * as d3 from 'd3';
import { knowledgeGraphService } from '../services/api';
import './KnowledgeGraph.css';

const { Title, Text } = Typography;
const { Option } = Select;

interface GraphNode {
  id: string;
  name: string;
  group: string;
  size?: number;
  x?: number;
  y?: number;
  fx?: number;
  fy?: number;
  connections?: number;
}

interface GraphEdge {
  source: string;
  target: string;
  weight?: number;
  type?: string;
}

interface GraphData {
  nodes: GraphNode[];
  edges: GraphEdge[];
}

interface GraphSettings {
  nodeSize: number;
  linkDistance: number;
  chargeStrength: number;
  showLabels: boolean;
  showEdges: boolean;
  colorByType: boolean;
  nodeSizeByConnections: boolean;
  animationSpeed: number;
}

const KnowledgeGraph: React.FC = () => {
  const [graphData, setGraphData] = useState<GraphData | null>(null);
  const [filteredData, setFilteredData] = useState<GraphData | null>(null);
  const [loading, setLoading] = useState(false);
  const [building, setBuilding] = useState(false);
  const [selectedNode, setSelectedNode] = useState<GraphNode | null>(null);
  const [showDetails, setShowDetails] = useState(false);
  const [searchTerm, setSearchTerm] = useState('');
  const [filterType, setFilterType] = useState('all');
  const [hoveredNode, setHoveredNode] = useState<string | null>(null);
  const hoverTimeoutRef = useRef<NodeJS.Timeout | null>(null);

  const svgRef = useRef<SVGSVGElement>(null);
  const simulationRef = useRef<d3.Simulation<GraphNode, GraphEdge> | null>(null);

  // Obsidian风格的设置
  const [settings, setSettings] = useState<GraphSettings>({
    nodeSize: 12,
    linkDistance: 80,
    chargeStrength: -400,
    showLabels: true,
    showEdges: true,
    colorByType: true,
    nodeSizeByConnections: true,
    animationSpeed: 0.3,
  });

  // 加载图谱数据
  const loadGraphData = async () => {
    try {
      setLoading(true);
      const response = await knowledgeGraphService.getGraph();
      
      // 检查响应结构
      if (response) {
        // 如果后端直接返回数据（API拦截器已经解包了response.data）
        if ((response as any).nodes && (response as any).edges) {
          const data = response as any;
          // 计算每个节点的连接数
          const nodesWithConnections = data.nodes.map((node: GraphNode) => {
            const connections = data.edges.filter((edge: GraphEdge) => 
              edge.source === node.id || edge.target === node.id
            ).length;
            return { ...node, connections };
          });
          
          setGraphData({ ...data, nodes: nodesWithConnections });
          setFilteredData({ ...data, nodes: nodesWithConnections });
        }
        // 如果后端返回的是包装后的数据结构
        else if ((response as any).success && (response as any).data) {
          const data = (response as any).data;
          // 计算每个节点的连接数
          const nodesWithConnections = data.nodes.map((node: GraphNode) => {
            const connections = data.edges.filter((edge: GraphEdge) => 
              edge.source === node.id || edge.target === node.id
            ).length;
            return { ...node, connections };
          });
          
          setGraphData({ ...data, nodes: nodesWithConnections });
          setFilteredData({ ...data, nodes: nodesWithConnections });
        }
        // 如果没有数据，创建示例数据
        else {
          const sampleData = {
            nodes: [
              { id: '1', name: '示例文件1', group: 'file', connections: 2 },
              { id: '2', name: '示例概念1', group: 'concept', connections: 3 },
              { id: '3', name: '示例主题1', group: 'topic', connections: 1 },
              { id: '4', name: '示例实体1', group: 'entity', connections: 2 },
              { id: '5', name: '示例笔记1', group: 'note', connections: 1 },
            ],
            edges: [
              { source: '1', target: '2' },
              { source: '2', target: '3' },
              { source: '2', target: '4' },
              { source: '3', target: '5' },
              { source: '4', target: '5' },
            ]
          };
          setGraphData(sampleData);
          setFilteredData(sampleData);
        }
      } else {
        message.error('API响应格式错误');
      }
    } catch (error) {
      console.error('加载图谱数据失败:', error);
      // 创建示例数据作为fallback
      const sampleData = {
        nodes: [
          { id: '1', name: '示例文件1', group: 'file', connections: 2 },
          { id: '2', name: '示例概念1', group: 'concept', connections: 3 },
          { id: '3', name: '示例主题1', group: 'topic', connections: 1 },
          { id: '4', name: '示例实体1', group: 'entity', connections: 2 },
          { id: '5', name: '示例笔记1', group: 'note', connections: 1 },
        ],
        edges: [
          { source: '1', target: '2' },
          { source: '2', target: '3' },
          { source: '2', target: '4' },
          { source: '3', target: '5' },
          { source: '4', target: '5' },
        ]
      };
      setGraphData(sampleData);
      setFilteredData(sampleData);
      message.warning('使用示例数据，请先构建图谱');
    } finally {
      setLoading(false);
    }
  };

  // 构建图谱
  const buildGraph = async () => {
    try {
      setBuilding(true);
      const response = await knowledgeGraphService.buildGraph();
      console.log('构建图谱API响应:', response);
      
      // 检查响应结构
      if (response && response.data) {
        // 如果后端返回的是包装后的数据结构
        if (response.data.success) {
          message.success('图谱构建成功');
          await loadGraphData();
        }
        // 如果后端返回的是直接的成功响应
        else if (response.data.message && response.data.message.includes('成功')) {
          message.success('图谱构建成功');
          await loadGraphData();
        }
        // 其他情况
        else {
          message.error('图谱构建失败');
        }
      } else {
        message.error('API响应格式错误');
      }
    } catch (error) {
      console.error('构建图谱失败:', error);
      message.error('构建图谱失败');
    } finally {
      setBuilding(false);
    }
  };

  // 重置布局
  const resetLayout = () => {
    if (simulationRef.current) {
      // 释放所有节点的位置固定
      simulationRef.current.nodes().forEach((node: any) => {
        node.fx = undefined;
        node.fy = undefined;
      });
      // 重新启动力导向模拟
      simulationRef.current.alphaTarget(0.3).restart();
      message.success('布局已重置');
    }
  };

  // 创建Obsidian风格的知识图谱
  const createForceGraph = useCallback(() => {
    if (!filteredData || !svgRef.current) {
      return;
    }

    const svg = d3.select(svgRef.current);
    svg.selectAll('*').remove();

    // 获取容器尺寸
    const container = svgRef.current.parentElement;
    const width = container ? container.clientWidth : 800;
    const height = container ? container.clientHeight : 600;

    svg.attr('width', width).attr('height', height);

    // 创建主容器
    const container_g = svg.append('g');

    // 创建力导向模拟 - Obsidian风格
    const simulation = d3.forceSimulation<GraphNode>(filteredData.nodes)
      .force('link', d3.forceLink<GraphNode, GraphEdge>(filteredData.edges)
        .id(d => d.id)
        .distance(settings.linkDistance)
        .strength(0.1)
      )
      .force('charge', d3.forceManyBody().strength(settings.chargeStrength))
      .force('center', d3.forceCenter(width / 2, height / 2))
      .force('collision', d3.forceCollide().radius((d: any) => getNodeRadius(d as GraphNode) + 5))
      .alphaDecay(0.01)
      .velocityDecay(0.3)
      .alpha(0.1);

    simulationRef.current = simulation;

    // 获取节点半径
    function getNodeRadius(d: GraphNode): number {
      if (settings.nodeSizeByConnections && d.connections) {
        return Math.max(settings.nodeSize, Math.min(settings.nodeSize * 2, d.connections * 2));
      }
      return settings.nodeSize;
    }

    // 获取节点颜色
    function getNodeColor(d: GraphNode): string {
      if (settings.colorByType) {
        const colors = {
          'file': '#1890ff',
          'concept': '#52c41a',
          'topic': '#faad14',
          'entity': '#f5222d',
          'note': '#722ed1',
          'tag': '#13c2c2'
        };
        return colors[d.group as keyof typeof colors] || '#d9d9d9';
      }
      return '#1890ff';
    }

    // 创建连线
    const link = container_g.append('g')
      .attr('class', 'links')
      .selectAll('line')
      .data(filteredData.edges)
      .enter().append('line')
      .attr('stroke', '#d9d9d9')
      .attr('stroke-opacity', settings.showEdges ? 0.6 : 0)
      .attr('stroke-width', 1.5)
      .style('transition', 'none');

    // 创建节点
    const node = container_g.append('g')
      .attr('class', 'nodes')
      .selectAll('circle')
      .data(filteredData.nodes)
      .enter().append('circle')
      .attr('r', getNodeRadius)
      .attr('fill', getNodeColor)
      .attr('stroke', '#FFFFFF')
      .attr('stroke-width', 2)
      .style('cursor', 'pointer')
      .style('transition', 'none')
      .call(d3.drag<SVGCircleElement, GraphNode>()
        .on('start', dragstarted)
        .on('drag', dragged)
        .on('end', dragended)
      )
      .on('click', (event, d) => {
        setSelectedNode(d);
        setShowDetails(true);
        
        // 点击时释放所有节点的位置固定，让图谱重新布局
        if (simulationRef.current) {
          simulationRef.current.nodes().forEach((node: any) => {
            node.fx = undefined;
            node.fy = undefined;
          });
          simulationRef.current.alphaTarget(0.1).restart();
        }
      })
      .on('mouseover', function(event, d) {
        // 清除之前的超时
        if (hoverTimeoutRef.current) {
          clearTimeout(hoverTimeoutRef.current);
        }
        
        setHoveredNode(d.id);
        
        // 立即固定当前节点位置，防止任何移动
        d.fx = d.x;
        d.fy = d.y;
        
        // 暂停力导向模拟
        if (simulationRef.current) {
          simulationRef.current.alphaTarget(0);
        }
        
        // 高亮当前节点 - 不使用过渡，直接设置
        d3.select(this)
          .attr('r', getNodeRadius(d) * 1.1)
          .attr('stroke-width', 3)
          .style('filter', 'drop-shadow(0 0 8px rgba(24, 144, 255, 0.8))');
        
        // 高亮相关连线 - 不使用过渡，直接设置
        link
          .style('stroke-opacity', l => {
            return ((l.source as unknown as GraphNode).id === d.id || 
                   (l.target as unknown as GraphNode).id === d.id) ? 1 : 0.1;
          })
          .style('stroke', l => {
            return ((l.source as unknown as GraphNode).id === d.id || 
                   (l.target as unknown as GraphNode).id === d.id) ? '#1890ff' : '#d9d9d9';
          })
          .style('stroke-width', l => {
            return ((l.source as unknown as GraphNode).id === d.id || 
                   (l.target as unknown as GraphNode).id === d.id) ? 2.5 : 1.5;
          });
      })
      .on('mouseout', function(event, d) {
        // 延迟恢复，避免快速悬停时的冲突
        hoverTimeoutRef.current = setTimeout(() => {
          setHoveredNode(null);
          
          // 恢复节点状态 - 不使用过渡，直接设置
          d3.select(this)
            .attr('r', getNodeRadius(d))
            .attr('stroke-width', 2)
            .style('filter', 'none');
          
          // 恢复连线状态 - 不使用过渡，直接设置
          link
            .style('stroke-opacity', settings.showEdges ? 0.6 : 0)
            .style('stroke', '#d9d9d9')
            .style('stroke-width', 1.5);
          
          // 保持节点位置固定，避免闪动到其他位置
          // 不释放 d.fx 和 d.fy，让节点保持在当前位置
          
          // 重新启动力导向模拟，但保持当前节点位置
          if (simulationRef.current) {
            simulationRef.current.alphaTarget(0.01).restart();
          }
        }, 50);
      });

    // 创建标签
    const labels = container_g.append('g')
      .attr('class', 'labels')
      .selectAll('text')
      .data(filteredData.nodes)
      .enter().append('text')
      .text(d => settings.showLabels ? d.name : '')
      .attr('font-size', '11px')
      .attr('font-family', 'Inter, -apple-system, BlinkMacSystemFont, sans-serif')
      .attr('font-weight', '500')
      .attr('fill', '#262626')
      .attr('text-anchor', 'middle')
      .attr('dy', d => getNodeRadius(d) + 15)
      .style('pointer-events', 'none')
      .style('text-shadow', '1px 1px 2px rgba(255, 255, 255, 0.8)')
      .style('transition', `opacity ${settings.animationSpeed}s ease`);

    // 添加缩放功能
    const zoom = d3.zoom<SVGSVGElement, unknown>()
      .scaleExtent([0.1, 4])
      .on('zoom', (event) => {
        container_g.attr('transform', event.transform);
      });

    svg.call(zoom);

    // 拖拽函数
    function dragstarted(event: d3.D3DragEvent<SVGCircleElement, GraphNode, GraphNode>, d: GraphNode) {
      if (!event.active) simulation.alphaTarget(0.3).restart();
      d.fx = d.x;
      d.fy = d.y;
      // 拖拽开始时禁用悬停效果
      d3.select(event.sourceEvent.target).style('pointer-events', 'none');
    }

    function dragged(event: d3.D3DragEvent<SVGCircleElement, GraphNode, GraphNode>, d: GraphNode) {
      d.fx = event.x;
      d.fy = event.y;
    }

    function dragended(event: d3.D3DragEvent<SVGCircleElement, GraphNode, GraphNode>, d: GraphNode) {
      if (!event.active) simulation.alphaTarget(0);
      // 拖拽结束后保持节点位置固定，避免闪动
      // d.fx = undefined;
      // d.fy = undefined;
      // 拖拽结束时恢复悬停效果
      d3.select(event.sourceEvent.target).style('pointer-events', 'auto');
    }

    // 更新位置
    simulation.on('tick', () => {
      link
        .attr('x1', d => (d.source as unknown as GraphNode).x!)
        .attr('y1', d => (d.source as unknown as GraphNode).y!)
        .attr('x2', d => (d.target as unknown as GraphNode).x!)
        .attr('y2', d => (d.target as unknown as GraphNode).y!);

      // 只更新非固定位置的节点
      node
        .attr('cx', d => d.x!)
        .attr('cy', d => d.y!);

      labels
        .attr('x', d => d.x!)
        .attr('y', d => d.y!);
    });

    // 移除持续运动，避免与悬停效果冲突
    // setInterval(() => {
    //   if (simulationRef.current) {
    //     simulationRef.current.alpha(0.1).restart();
    //   }
    // }, 10000);
  }, [filteredData, settings]);

  // 重置视图
  const resetView = () => {
    if (svgRef.current) {
      const svg = d3.select(svgRef.current);
      svg.transition().duration(750).call(
        d3.zoom<SVGSVGElement, unknown>().transform,
        d3.zoomIdentity
      );
    }
  };

  // 重新布局图谱
  const relayoutGraph = () => {
    if (simulationRef.current) {
      // 释放所有节点的位置固定
      simulationRef.current.nodes().forEach((node: any) => {
        node.fx = undefined;
        node.fy = undefined;
      });
      // 重新启动力导向模拟
      simulationRef.current.alpha(0.3).restart();
      message.success('图谱布局已重置');
    }
  };

  // 过滤数据
  const filteredGraphData = React.useMemo(() => {
    if (!graphData) return null;

    let filteredNodes = [...graphData.nodes];
    let filteredEdges = [...graphData.edges];

    // 按搜索词过滤
    if (searchTerm) {
      const searchLower = searchTerm.toLowerCase();
      filteredNodes = filteredNodes.filter(node =>
        node.name.toLowerCase().includes(searchLower)
      );
      const nodeIds = new Set(filteredNodes.map(n => n.id));
      filteredEdges = filteredEdges.filter(edge =>
        nodeIds.has(edge.source) && nodeIds.has(edge.target)
      );
    }

    // 按类型过滤
    if (filterType !== 'all') {
      filteredNodes = filteredNodes.filter(node => node.group === filterType);
      const nodeIds = new Set(filteredNodes.map(n => n.id));
      filteredEdges = filteredEdges.filter(edge =>
        nodeIds.has(edge.source) && nodeIds.has(edge.target)
      );
    }

    return {
      nodes: filteredNodes,
      edges: filteredEdges,
      stats: {
        totalNodes: filteredNodes.length,
        totalEdges: filteredEdges.length,
        fileNodes: filteredNodes.filter(n => n.group === 'file').length,
        conceptNodes: filteredNodes.filter(n => n.group === 'concept').length,
        topicNodes: filteredNodes.filter(n => n.group === 'topic').length,
      }
    };
  }, [graphData, searchTerm, filterType]);

  // 创建图谱
  useEffect(() => {
    if (filteredGraphData) {
      setFilteredData(filteredGraphData);
    }
  }, [filteredGraphData, settings]);

  // 窗口大小变化监听
  useEffect(() => {
    const handleResize = () => {
      if (graphData) {
        createForceGraph();
      }
    };

    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, [graphData, createForceGraph]);

  // 初始加载
  useEffect(() => {
    loadGraphData();
  }, []);

  // 当filteredData变化时直接创建图谱
  useEffect(() => {
    if (filteredData && svgRef.current) {
      createForceGraph();
    }
  }, [filteredData, createForceGraph]);

  return (
    <div className="knowledge-graph-container">
      <Row gutter={16} style={{ height: '100%' }}>
        {/* 左侧控制面板 */}
        <Col span={6}>
          <Card title="知识图谱控制台" size="small" style={{ height: '100%' }}>
            <Space direction="vertical" style={{ width: '100%' }}>
              {/* 操作按钮 */}
              <Space wrap>
                <Button
                  type="primary"
                  icon={building ? <Spin size="small" /> : <ReloadOutlined />}
                  onClick={buildGraph}
                  loading={building}
                  disabled={building}
                >
                  {building ? '构建中...' : '构建图谱'}
                </Button>
                <Button
                  icon={loading ? <Spin size="small" /> : <ReloadOutlined />}
                  onClick={loadGraphData}
                  loading={loading}
                  disabled={loading}
                >
                  {loading ? '加载中...' : '刷新数据'}
                </Button>
                <Button
                  icon={<ReloadOutlined />}
                  onClick={() => {
                    console.log('强制刷新图谱');
                    if (filteredData) {
                      createForceGraph();
                    }
                  }}
                >
                  强制刷新图谱
                </Button>
              </Space>

              <Divider />

              {/* 搜索和过滤 */}
              <div>
                <Text strong>搜索节点</Text>
                <Input
                  placeholder="输入节点名称"
                  prefix={<SearchOutlined />}
                  value={searchTerm}
                  onChange={(e) => setSearchTerm(e.target.value)}
                  style={{ marginTop: 8 }}
                />
              </div>

              <div>
                <Text strong>节点类型</Text>
                <Select
                  value={filterType}
                  onChange={setFilterType}
                  style={{ width: '100%', marginTop: 8 }}
                >
                  <Option value="all">全部</Option>
                  <Option value="file">文件</Option>
                  <Option value="concept">概念</Option>
                  <Option value="topic">主题</Option>
                  <Option value="entity">实体</Option>
                  <Option value="note">笔记</Option>
                  <Option value="tag">标签</Option>
                </Select>
              </div>

              <Divider />

              {/* Obsidian风格设置 */}
              <div>
                <Text strong>图谱设置</Text>
                <div style={{ marginTop: 8 }}>
                  <div style={{ marginBottom: 16 }}>
                    <Text>节点大小: {settings.nodeSize}</Text>
                    <Slider
                      min={6}
                      max={20}
                      value={settings.nodeSize}
                      onChange={(value) => setSettings(prev => ({ ...prev, nodeSize: value }))}
                    />
                  </div>

                  <div style={{ marginBottom: 16 }}>
                    <Text>连接距离: {settings.linkDistance}</Text>
                    <Slider
                      min={50}
                      max={150}
                      value={settings.linkDistance}
                      onChange={(value) => setSettings(prev => ({ ...prev, linkDistance: value }))}
                    />
                  </div>

                  <div style={{ marginBottom: 16 }}>
                    <Text>电荷强度: {settings.chargeStrength}</Text>
                    <Slider
                      min={-600}
                      max={-100}
                      value={settings.chargeStrength}
                      onChange={(value) => setSettings(prev => ({ ...prev, chargeStrength: value }))}
                    />
                  </div>

                  <div style={{ marginBottom: 16 }}>
                    <Text>动画速度: {settings.animationSpeed}s</Text>
                    <Slider
                      min={0.1}
                      max={1.0}
                      step={0.1}
                      value={settings.animationSpeed}
                      onChange={(value) => setSettings(prev => ({ ...prev, animationSpeed: value }))}
                    />
                  </div>

                  <div style={{ marginBottom: 16 }}>
                    <Switch
                      checked={settings.showLabels}
                      onChange={(checked) => setSettings(prev => ({ ...prev, showLabels: checked }))}
                    />
                    <Text style={{ marginLeft: 8 }}>显示标签</Text>
                  </div>

                  <div style={{ marginBottom: 16 }}>
                    <Switch
                      checked={settings.showEdges}
                      onChange={(checked) => setSettings(prev => ({ ...prev, showEdges: checked }))}
                    />
                    <Text style={{ marginLeft: 8 }}>显示连线</Text>
                  </div>

                  <div style={{ marginBottom: 16 }}>
                    <Switch
                      checked={settings.colorByType}
                      onChange={(checked) => setSettings(prev => ({ ...prev, colorByType: checked }))}
                    />
                    <Text style={{ marginLeft: 8 }}>按类型着色</Text>
                  </div>

                  <div style={{ marginBottom: 16 }}>
                    <Switch
                      checked={settings.nodeSizeByConnections}
                      onChange={(checked) => setSettings(prev => ({ ...prev, nodeSizeByConnections: checked }))}
                    />
                    <Text style={{ marginLeft: 8 }}>节点大小反映连接数</Text>
                  </div>
                </div>
              </div>

              <Divider />

              {/* 统计信息 */}
              {filteredGraphData && (
                <div>
                  <Text strong>统计信息</Text>
                  <div style={{ marginTop: 8 }}>
                    <Statistic title="总节点数" value={filteredGraphData.stats.totalNodes} />
                    <Statistic title="总连接数" value={filteredGraphData.stats.totalEdges} />
                    <Statistic title="文件节点" value={filteredGraphData.stats.fileNodes} />
                    <Statistic title="概念节点" value={filteredGraphData.stats.conceptNodes} />
                    <Statistic title="主题节点" value={filteredGraphData.stats.topicNodes} />
                  </div>
                </div>
              )}

              <Divider />

              {/* 视图控制 */}
              <div>
                <Text strong>视图控制</Text>
                <Space wrap style={{ marginTop: 8 }}>
                  <Tooltip title="放大">
                    <Button icon={<ZoomInOutlined />} onClick={() => {
                      if (svgRef.current) {
                        const svg = d3.select(svgRef.current);
                        svg.transition().duration(300).call(
                          d3.zoom<SVGSVGElement, unknown>().scaleBy, 1.5
                        );
                      }
                    }} />
                  </Tooltip>
                  <Tooltip title="缩小">
                    <Button icon={<ZoomOutOutlined />} onClick={() => {
                      if (svgRef.current) {
                        const svg = d3.select(svgRef.current);
                        svg.transition().duration(300).call(
                          d3.zoom<SVGSVGElement, unknown>().scaleBy, 1 / 1.5
                        );
                      }
                    }} />
                  </Tooltip>
                  <Tooltip title="重置视图">
                    <Button icon={<FullscreenOutlined />} onClick={resetView} />
                  </Tooltip>
                  <Tooltip title="重新布局">
                    <Button icon={<ReloadOutlined />} onClick={relayoutGraph} />
                  </Tooltip>
                </Space>
              </div>
            </Space>
          </Card>
        </Col>

        {/* 右侧图谱显示区域 */}
        <Col span={18}>
          <Card style={{ height: '100%' }}>
            <div style={{ height: '70vh', minHeight: '500px', position: 'relative' }}>
              {loading ? (
                <div style={{ 
                  display: 'flex', 
                  justifyContent: 'center', 
                  alignItems: 'center', 
                  height: '100%' 
                }}>
                  <Spin size="large" />
                </div>
              ) : (
                <svg ref={svgRef} style={{ width: '100%', height: '100%' }} />
              )}
            </div>
          </Card>
        </Col>
      </Row>

      {/* 节点详情抽屉 */}
      <Drawer
        title="节点详情"
        placement="right"
        onClose={() => setShowDetails(false)}
        open={showDetails}
        width={400}
      >
        {selectedNode && (
          <div>
            <Title level={4}>{selectedNode.name}</Title>
            <Divider />
            <List
              dataSource={[
                { label: 'ID', value: selectedNode.id },
                { label: '类型', value: selectedNode.group },
                { label: '连接数', value: selectedNode.connections || 0 },
                { label: 'X坐标', value: selectedNode.x?.toFixed(2) },
                { label: 'Y坐标', value: selectedNode.y?.toFixed(2) },
              ]}
              renderItem={item => (
                <List.Item>
                  <Text strong>{item.label}:</Text>
                  <Text style={{ marginLeft: 8 }}>{item.value}</Text>
                </List.Item>
              )}
            />
          </div>
        )}
      </Drawer>
    </div>
  );
};

export default KnowledgeGraph;